package com.shangxia.monomer.study.thread.base.util;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @ProjectName: monomer
 * @ClassName: ReadWriteLockDemo
 * @Time: 2021/10/1
 * @Author: zhouy
 * @Description:
 * @Experience:
 */

@Slf4j
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        // put 方法会被插队
        //Cache cache = new MyCache();

        Cache cache = new MyCacheLock();

        for (int i = 0; i < 5; i++) {
            final int temp = i;
            new Thread(() -> {
                cache.put("key" + temp, new Object());
            }, "" + i).start();
        }

        for (int i = 0; i < 5; i++) {
            final int temp = i;
            new Thread(() -> {
                cache.get("key" + temp);
            }, "" + i).start();
        }

    }

    static class MyCacheLock implements Cache {
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        Lock readLock = readWriteLock.readLock();
        Lock writeLock = readWriteLock.writeLock();
        private volatile Map<String, Object> cacheMap = new HashMap<>();

        @Override
        public void put(String key, Object value) {
            writeLock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + key + "添加开始");
                cacheMap.put(key, value);
                System.out.println(Thread.currentThread().getName() + key + "添加 OK");
            } finally {
                writeLock.unlock();
            }

        }

        @Override
        public Object get(String key) {
            Object o;
            readLock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + key + "查询开始");
                o = cacheMap.get(key);
                System.out.println(Thread.currentThread().getName() + key + "查询 OK");
            } finally {
                readLock.unlock();
            }
            return o;
        }

    }

    static class MyCache implements Cache {
        private volatile Map<String, Object> cacheMap = new HashMap<>();

        @Override
        public void put(String key, Object value) {
            System.out.println(Thread.currentThread().getName() + key + "添加开始");
            cacheMap.put(key, value);
            System.out.println(Thread.currentThread().getName() + key + "OK");

        }

        @Override
        public Object get(String key) {
            System.out.println(Thread.currentThread().getName() + key + "添加开始");
            Object o = cacheMap.get(key);
            System.out.println(Thread.currentThread().getName() + key + "OK");
            return o;
        }

    }

    interface Cache {
        void put(String key, Object value);

        Object get(String key);
    }
}

